package com.cd.javacxy.module.web.service.impl;

import com.cd.javacxy.common.model.entity.CxyAsk;
import com.cd.javacxy.common.model.entity.CxyComment;
import com.cd.javacxy.common.model.enums.*;
import com.cd.javacxy.common.model.query.AskQuery;
import com.cd.javacxy.common.model.query.MessageParams;
import com.cd.javacxy.common.model.query.UpdateQuery4ArticleCount;
import com.cd.javacxy.common.model.vo.CxyUserVo;
import com.cd.javacxy.common.utils.CxyUtils;
import com.cd.javacxy.common.utils.ImageUtils;
import com.cd.javacxy.common.utils.Page;
import com.cd.javacxy.common.utils.PageResult;
import com.cd.javacxy.exception.BaseException;
import com.cd.javacxy.exception.BussinessException;
import com.cd.javacxy.module.web.dao.CxyAskDao;
import com.cd.javacxy.module.web.service.CxyAskService;
import com.cd.javacxy.module.web.service.CxyCommentService;
import com.cd.javacxy.module.web.service.CxyMessageService;
import com.cd.javacxy.module.web.service.CxyUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * CxyAsk的服务接口的实现类
 *
 * @author yanghy
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CxyAskServiceImpl implements CxyAskService {


    private final CxyAskDao askDao;

    private final CxyUserService userService;

    private final CxyCommentService commentService;

    private final FormateAtService formateAtService;

    private final CxyMessageService messageService;

    @Override
    public PageResult<CxyAsk> findAskByPage(AskQuery askQuery) {
        int count = this.findCount(askQuery);
        int pageNum = askQuery.getPageNum();
        int pageSize = PageSize.PAGE_SIZE20.getSize();
        askQuery.setOrderBy(OrderByEnum.CREATE_TIME_DESC);
        Page page = new Page(pageNum, count, pageSize);
        List<CxyAsk> list = this.askDao.selectList(askQuery);
        return new PageResult<>(page, list);
    }

    @Override
    public int findCount(AskQuery askQuery) {
        return this.askDao.selectCount(askQuery);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void addAsk(CxyAsk cxyAsk) {
        CxyUserVo user = this.userService.findUserByUserId(cxyAsk.getUserId());
        if (user.getMark() < cxyAsk.getMark()) {
            throw new BaseException("积分不足 " + user.getMark() + " 分");
        }
        String title = cxyAsk.getTitle();
        cxyAsk.setTitle(HtmlUtils.htmlEscape(title));
        String content = cxyAsk.getContent();
        String summary = CxyUtils.cleanHtmlTag(HtmlUtils.htmlUnescape(content));
        if (summary.length() > TextLengthEnum.TEXT_200_LENGTH.getLength()) {
            summary = summary.substring(0,
                    (int) TextLengthEnum.TEXT_200_LENGTH.getLength())
                    + "......";
        }
        Set<Integer> userIds = new HashSet<>();
        String formatContent = formateAtService.generateRefererLinks(content,
                userIds);
        // TODO 给用户发消息
        cxyAsk.setSummary(summary);
        cxyAsk.setContent(formatContent);
        String askImage = ImageUtils.getImages(content);
        cxyAsk.setAskImage(askImage);
        String askImageSmall = ImageUtils.createThumbnail(askImage, true);
        cxyAsk.setAskImageThum(askImageSmall);
        cxyAsk.setCreateTime(LocalDateTime.now());
        cxyAsk.setSolveType(SolveEnum.WAIT_SOLVE);
        this.askDao.insert(cxyAsk);
        this.userService.changeMark(cxyAsk.getUserId(), cxyAsk.getMark());

        MessageParams messageParams = new MessageParams();
        messageParams.setArticleId(cxyAsk.getAskId());
        messageParams.setArticleType(ArticleType.Ask);
        messageParams.setArticleUserId(cxyAsk.getUserId());
        messageParams.setMessageType(MessageType.AT_ARTICLE_MESSAGE);
        messageParams.setSendUserName(cxyAsk.getUserName());
        messageParams.setSendUserId(cxyAsk.getUserId());
        messageParams.setReceiveUserIds(userIds);
        messageService.createMessage(messageParams);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void setBestAnswer(Integer bestAnswerId, Integer askId, Integer userId) {
        CxyAsk cxyAsk = this.getAskById(askId);
        if (cxyAsk.getSolveType() == SolveEnum.SOLVED) {
            throw new BaseException("参数错误");
        }
        CxyComment comment = this.commentService.getCommentById(bestAnswerId);
        if (comment == null || comment.getArticleId().intValue() != askId) {
            throw new BaseException("参数错误");
        }
        cxyAsk.setBestAnswerId(bestAnswerId);
        cxyAsk.setAskId(askId);
        cxyAsk.setBestAnswerUserId(comment.getUserId());
        cxyAsk.setBestAnswerUserName(comment.getUserName());
        cxyAsk.setBestAnswerUserIcon(comment.getUserIcon());
        cxyAsk.setSolveType(SolveEnum.SOLVED);
        this.askDao.updateBestAnswer(cxyAsk);
        this.userService.addMark(cxyAsk.getMark(), userId);
        //TODO给用户发消息
        MessageParams messageParams = new MessageParams();
        messageParams.setArticleId(askId);
        messageParams.setArticleType(ArticleType.Ask);
        messageParams.setArticleUserId(cxyAsk.getUserId());
        messageParams.setMessageType(MessageType.ADOPT_ANSWER);
        messageParams.setSendUserName(cxyAsk.getUserName());
        messageParams.setSendUserId(userId);
        Set<Integer> userIds = new HashSet<>();
        userIds.add(comment.getUserId());
        messageParams.setReceiveUserIds(userIds);
        messageService.createMessage(messageParams);
    }

    @Override
    public CxyAsk getAskById(Integer askId) {
        if (askId == null) {
            return null;
        }
        AskQuery askQuery = new AskQuery();
        askQuery.setAskId(askId);
        askQuery.setShowContent(Boolean.TRUE);
        List<CxyAsk> list = this.askDao.selectList(askQuery);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public CxyAsk showAsk(Integer askId) throws BussinessException {
        CxyAsk cxyAsk = this.getAskById(askId);
        if (cxyAsk == null) {
            throw new BussinessException("问答不存在或已删除");
        }
        if (cxyAsk.getSolveType() == SolveEnum.SOLVED) {
            cxyAsk.setBestAnswer(this.commentService.getCommentById(cxyAsk.getBestAnswerId()));
        }
        UpdateQuery4ArticleCount updateQuery4ArticleCount = new UpdateQuery4ArticleCount();
        updateQuery4ArticleCount.setAddReadCount(Boolean.TRUE);
        updateQuery4ArticleCount.setArticleId(cxyAsk.getAskId());
        this.askDao.updateInfoCount(updateQuery4ArticleCount);
        return cxyAsk;
    }

    @Override
    public List<CxyAsk> findTopUsers() {
        AskQuery askQuery = new AskQuery();
        askQuery.setTopCount(10);
        return this.askDao.selectTopUser(askQuery);
    }

    @Override
    public List<CxyAsk> findAskList() {
        AskQuery askQuery = new AskQuery();
        askQuery.setOrderBy(OrderByEnum.CREATE_TIME_DESC);
        return askDao.selectList(askQuery);
    }

    @Override
    public void deleteBatch(Integer[] ids) throws BussinessException {
        if (ids == null) {
            throw new BussinessException("参数错误");
        }
        for (int id : ids) {
            askDao.delete(id);
        }
    }


}